﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Fwql.Net.Utils;
using Microsoft.VisualBasic;

namespace Fwql.Net.Extensions
{
    public static class StringExtension
    {
        #region Conversion

        #region ConvertToBoolean

        /// <summary>
        /// 将字符串转换成Boolean(yes/no/true/false/0/1)
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果</returns>
        public static bool ToBool(this string origin, bool defaultValue = false)
        {
            if (string.IsNullOrEmpty(origin))
                return defaultValue;

            switch (origin.ToUpper())
            {
                case "YES":
                case "TRUE":
                case "1":
                    return true;
                default:
                    return false;
            }
        }

        #endregion

        #region ConvertToInt32

        /// <summary>
        /// 将字符串转换成Int32
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果</returns>
        public static int ToInt(this string origin, int defaultValue = 0)
        {
            int outValue;
            if (int.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }

        #endregion

        #region ConvertToInt64

        /// <summary>
        /// 将字符串转换成Int64
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果</returns>
        public static long ConvertToInt64(this string origin, long defaultValue = 0L)
        {
            long outValue;
            if (long.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }

        #endregion

        #region ConvertToFloat

        /// <summary>
        /// 将字符串转换成Float
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果。</returns>
        public static float ConvertToFloat(this string origin, float defaultValue = 0f)
        {
            float outValue;
            if (float.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }

        #endregion

        #region ConvertToDouble

        /// <summary>
        /// 将字符串转换成Double
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果</returns>
        public static double ToDouble(this string origin, double defaultValue = 0d)
        {
            double outValue;
            if (double.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }

        #endregion

        #region ConvertToDateTime

        /// <summary>
        /// 将字符串转换成DateTime
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>转换结果，转换失败，默认返回当前时间</returns>
        public static DateTime ToDateTime(this string origin)
        {
            DateTime outValue;
            if (DateTime.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return DateTime.Now;
        }

        /// <summary>
        /// 将字符串转换成DateTime
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>转换结果</returns>
        public static DateTime ToDateTime(this string origin, DateTime defaultValue)
        {
            DateTime outValue;
            if (DateTime.TryParse(origin, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }

        #endregion

        #region ConvertToGuid

        /// <summary>
        /// 将字符串转换成GUID，如果转换失败，那么返回Guid.NewGuid()
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static Guid ToGuid(this string value)
        {
            return value.ToGuid(Guid.NewGuid());
        }

        /// <summary>
        /// 将字符串转换成GUID，如果转换失败，那么返回指定的默认值
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "defaultValue"></param>
        /// <returns></returns>
        public static Guid ToGuid(this string value, Guid defaultValue)
        {
            if (value.HasValue() == false)
                return defaultValue;

            try
            {
                return Guid.Parse(value);
            }
            catch
            {
                return defaultValue;
            }
        }

        #endregion

        #endregion

        #region SubString

        /// <summary>
        /// 从左侧开始截取字符串
        /// </summary>
        /// <param name="input">源字符串</param>
        /// <param name="length">截取长度</param>
        /// <returns></returns>
        public static string Left(this string input, int length)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            length = length.Clamp(0, input.Length);
            return input.Substring(0, input.Length > length ? length : input.Length);
        }

        /// <summary>
        /// 从右侧开始截取字符串
        /// </summary>
        /// <param name="input">源字符串</param>
        /// <param name="length">截取长度</param>
        /// <returns></returns>
        public static string Right(this string input, int length)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            length = length.Clamp(0, input.Length);
            length = input.Length > length ? length : input.Length;
            return input.Substring(input.Length - length, length);
        }

        #endregion

        #region Validation

        /// <summary>
        /// 验证身份证号码
        /// </summary>
        /// <param name="s">身份证号码</param>
        /// <returns>验证成功为True，否则为False</returns>
        public static bool IsIdentityCard(this string s)
        {
            switch (s.Trim().Length)
            {
                case 18:
                    return CheckIdCard18(s);
                default:
                    return false;
            }
        }

        /// <summary>
        /// 是否为Int
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsInteger(this string s)
        {
            int i;
            return Int32.TryParse(s, out i);
        }

        /// <summary>
        /// 是否为Int
        /// </summary>
        /// <param name="s"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public static bool IsInteger(this string s, out int outValue)
        {
            return Int32.TryParse(s, out outValue);
        }

        /// <summary>
        /// 是否为Double
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsDouble(this string s)
        {
            double d;
            return double.TryParse(s, out d);
        }

        /// <summary>
        /// 是否为Double
        /// </summary>
        /// <param name="s"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public static bool IsDouble(this string s, out double outValue)
        {
            return double.TryParse(s, out outValue);
        }

        /// <summary>
        /// 是否为Long
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsLong(this string s)
        {
            long d;
            return long.TryParse(s, out d);
        }

        /// <summary>
        /// 是否为Long
        /// </summary>
        /// <param name="s"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public static bool IsLong(this string s, out long outValue)
        {
            return long.TryParse(s, out outValue);
        }

        /// <summary>
        /// 是否为DateTime
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string s)
        {
            DateTime dt;
            return DateTime.TryParse(s, out dt);
        }

        /// <summary>
        /// 是否为DateTime
        /// </summary>
        /// <param name="s"></param>
        /// <param name="outValue"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string s, out DateTime outValue)
        {
            return DateTime.TryParse(s, out outValue);
        }

        /// <summary>
        /// 是否包含SQL注入信息
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsSqlInjection(this string s)
        {
            return
                s.IsMatch(
                    @"\s?;\s?|\s?drop\s|\s?grant\s|^'|\s?--|\s?union\s|\s?delete\s|\s?truncate\s|\s?sysobjects\s?|\s?xp_.*?|\s?syslogins\s?|\s?sysremote\s?|\s?sysusers\s?|\s?sysxlogins\s?|\s?sysdatabases\s?|\s?aspnet_.*?|\s?exec\s?");
        }

        #region 私有方法

        /// <summary>
        /// 验证18位身份证号
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns>验证成功为True，否则为False</returns>
        private static bool CheckIdCard18(string id)
        {
            long n;
            if (long.TryParse(id.Remove(17), out n) == false || n < Math.Pow(10, 16) ||
                long.TryParse(id.Replace('x', '0').Replace('X', '0'), out n) == false)
            {
                return false; //数字验证
            }
            const string address =
                "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(id.Remove(2)) == -1)
            {
                return false; //省份验证
            }
            string birth = id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            DateTime time;
            if (DateTime.TryParse(birth, out time) == false)
            {
                return false; //生日验证
            }
            string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
            string[] wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
            char[] ai = id.Remove(17).ToCharArray();
            int sum = 0;
            for (int i = 0; i < 17; i++)
            {
                sum += int.Parse(wi[i])*int.Parse(ai[i].ToString());
            }
            int y;
            Math.DivRem(sum, 11, out y);
            if (arrVarifyCode[y] != id.Substring(17, 1).ToLower())
            {
                return false; //校验码验证
            }
            return true; //符合GB11643-1999标准
        }

        #endregion

        #endregion

        #region Chinese

        /// <summary>
        /// 把汉字转换成拼音(全拼)
        /// </summary>
        /// <param name="chineseString">汉字字符串</param>
        /// <returns>转换后的拼音(全拼)字符串</returns>
        public static string ToPinyin(this string chineseString)
        {
            #region 私有字段

            string[] pinyinName = {
                                      "A", "Ai", "An", "Ang", "Ao", "Ba", "Bai", "Ban", "Bang", "Bao", "Bei", "Ben",
                                      "Beng", "Bi", "Bian", "Biao", "Bie", "Bin", "Bing", "Bo", "Bu", "Ba", "Cai", "Can"
                                      , "Cang", "Cao", "Ce", "Ceng", "Cha", "Chai", "Chan", "Chang", "Chao", "Che",
                                      "Chen", "Cheng", "Chi", "Chong", "Chou", "Chu", "Chuai", "Chuan", "Chuang", "Chui"
                                      , "Chun", "Chuo", "Ci", "Cong", "Cou", "Cu", "Cuan", "Cui", "Cun", "Cuo", "Da",
                                      "Dai", "Dan", "Dang", "Dao", "De", "Deng", "Di", "Dian", "Diao", "Die", "Ding",
                                      "Diu", "Dong", "Dou", "Du", "Duan", "Dui", "Dun", "Duo", "E", "En", "Er", "Fa",
                                      "Fan", "Fang", "Fei", "Fen", "Feng", "Fo", "Fou", "Fu", "Ga", "Gai", "Gan", "Gang"
                                      , "Gao", "Ge", "Gei", "Gen", "Geng", "Gong", "Gou", "Gu", "Gua", "Guai", "Guan",
                                      "Guang", "Gui", "Gun", "Guo", "Ha", "Hai", "Han", "Hang", "Hao", "He", "Hei",
                                      "Hen", "Heng", "Hong", "Hou", "Hu", "Hua", "Huai", "Huan", "Huang", "Hui", "Hun",
                                      "Huo", "Ji", "Jia", "Jian", "Jiang", "Jiao", "Jie", "Jin", "Jing", "Jiong", "Jiu",
                                      "Ju", "Juan", "Jue", "Jun", "Ka", "Kai", "Kan", "Kang", "Kao", "Ke", "Ken", "Keng"
                                      , "Kong", "Kou", "Ku", "Kua", "Kuai", "Kuan", "Kuang", "Kui", "Kun", "Kuo", "La",
                                      "Lai", "Lan", "Lang", "Lao", "Le", "Lei", "Leng", "Li", "Lia", "Lian", "Liang",
                                      "Liao", "Lie", "Lin", "Ling", "Liu", "Long", "Lou", "Lu", "Lv", "Luan", "Lue",
                                      "Lun", "Luo", "Ma", "Mai", "Man", "Mang", "Mao", "Me", "Mei", "Men", "Meng", "Mi",
                                      "Mian", "Miao", "Mie", "Min", "Ming", "Miu", "Mo", "Mou", "Mu", "Na", "Nai", "Nan"
                                      , "Nang", "Nao", "Ne", "Nei", "Nen", "Neng", "Ni", "Nian", "Niang", "Niao", "Nie",
                                      "Nin", "Ning", "Niu", "Nong", "Nu", "Nv", "Nuan", "Nue", "Nuo", "O", "Ou", "Pa",
                                      "Pai", "Pan", "Pang", "Pao", "Pei", "Pen", "Peng", "Pi", "Pian", "Piao", "Pie",
                                      "Pin", "Ping", "Po", "Pu", "Qi", "Qia", "Qian", "Qiang", "Qiao", "Qie", "Qin",
                                      "Qing", "Qiong", "Qiu", "Qu", "Quan", "Que", "Qun", "Ran", "Rang", "Rao", "Re",
                                      "Ren", "Reng", "Ri", "Rong", "Rou", "Ru", "Ruan", "Rui", "Run", "Ruo", "Sa", "Sai"
                                      , "San", "Sang", "Sao", "Se", "Sen", "Seng", "Sha", "Shai", "Shan", "Shang",
                                      "Shao", "She", "Shen", "Sheng", "Shi", "Shou", "Shu", "Shua", "Shuai", "Shuan",
                                      "Shuang", "Shui", "Shun", "Shuo", "Si", "Song", "Sou", "Su", "Suan", "Sui", "Sun",
                                      "Suo", "Ta", "Tai", "Tan", "Tang", "Tao", "Te", "Teng", "Ti", "Tian", "Tiao",
                                      "Tie", "Ting", "Tong", "Tou", "Tu", "Tuan", "Tui", "Tun", "Tuo", "Wa", "Wai",
                                      "Wan", "Wang", "Wei", "Wen", "Weng", "Wo", "Wu", "Xi", "Xia", "Xian", "Xiang",
                                      "Xiao", "Xie", "Xin", "Xing", "Xiong", "Xiu", "Xu", "Xuan", "Xue", "Xun", "Ya",
                                      "Yan", "Yang", "Yao", "Ye", "Yi", "Yin", "Ying", "Yo", "Yong", "You", "Yu", "Yuan"
                                      , "Yue", "Yun", "Za", "Zai", "Zan", "Zang", "Zao", "Ze", "Zei", "Zen", "Zeng",
                                      "Zha", "Zhai", "Zhan", "Zhang", "Zhao", "Zhe", "Zhen", "Zheng", "Zhi", "Zhong",
                                      "Zhou", "Zhu", "Zhua", "Zhuai", "Zhuan", "Zhuang", "Zhui", "Zhun", "Zhuo", "Zi",
                                      "Zong", "Zou", "Zu", "Zuan", "Zui", "Zun", "Zuo"
                                  };

            int[] pinyinValue = {
                                    -20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230,
                                    -20051, -20036, -20032, -20026, -20002, -19990, -19986, -19982, -19976, -19805,
                                    -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
                                    -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467,
                                    -19289, -19288, -19281, -19275, -19270, -19263, -19261, -19249, -19243, -19242,
                                    -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006,
                                    -19003, -18996, -18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756,
                                    -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501,
                                    -18490, -18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220,
                                    -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988, -17970, -17964,
                                    -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730,
                                    -17721, -17703, -17701, -17697, -17692, -17683, -17676, -17496, -17487, -17482,
                                    -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942,
                                    -16915, -16733, -16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470,
                                    -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419, -16412,
                                    -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187,
                                    -16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944, -15933, -15920,
                                    -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659,
                                    -15652, -15640, -15631, -15625, -15454, -15448, -15436, -15435, -15419, -15416,
                                    -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
                                    -15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139,
                                    -15128, -15121, -15119, -15117, -15110, -15109, -14941, -14937, -14933, -14930,
                                    -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889,
                                    -14882, -14873, -14871, -14857, -14678, -14674, -14670, -14668, -14663, -14654,
                                    -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355,
                                    -14353, -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135,
                                    -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094, -14092, -14090,
                                    -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894,
                                    -13878, -13870, -13859, -13847, -13831, -13658, -13611, -13601, -13406, -13404,
                                    -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343,
                                    -13340, -13329, -13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095,
                                    -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860, -12858,
                                    -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594,
                                    -12585, -12556, -12359, -12346, -12320, -12300, -12120, -12099, -12089, -12074,
                                    -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604,
                                    -11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097, -11077, -11067,
                                    -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014,
                                    -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533,
                                    -10519, -10331, -10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281,
                                    -10274, -10270, -10262, -10260, -10256, -10254
                                };

            #endregion

            // 匹配中文字符
            var regex = new Regex("^[\u4e00-\u9fa5]$");
            string res = string.Empty;
            char[] temp = chineseString.ToCharArray();

            for (int j = 0; j < temp.Length; j++)
            {
                // 中文字符
                if (regex.IsMatch(temp[j].ToString()))
                {
                    byte[] array = Encoding.Default.GetBytes(temp[j].ToString());
                    int i1 = (array[0]);
                    int i2 = (array[1]);
                    int chrAsc = i1*256 + i2 - 65536;
                    if (chrAsc > 0 && chrAsc < 160)
                    {
                        res += temp[j];
                    }
                    else
                    {
                        // 修正部分文字
                        if (chrAsc == -9254) // 修正“圳”字
                            res += "Zhen";
                        else
                        {
                            for (int i = (pinyinValue.Length - 1); i >= 0; i--)
                            {
                                if (pinyinValue[i] <= chrAsc)
                                {
                                    res += pinyinName[i];
                                    break;
                                }
                            }
                        }
                    }
                }
                    // 非中文字符
                else
                {
                    res += temp[j].ToString();
                }
            }
            return res;
        }

        /// <summary>
        /// 转换为简体中文
        /// </summary>
        public static string ToSimplifiedChinese(this string str)
        {
            return Strings.StrConv(str, VbStrConv.SimplifiedChinese);
        }

        /// <summary>
        /// 转换为繁体中文
        /// </summary>
        public static string ToTraditionalChinese(this string str)
        {
            return Strings.StrConv(str, VbStrConv.TraditionalChinese);
        }

        #endregion

        #region Truncate

        /// <summary>
        /// 字符串截取
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="maxLength">截取长度</param>
        /// <param name="suffix">后缀</param>
        /// <returns>截取后的字符串</returns>
        public static string Truncate(string origin, int maxLength, string suffix = "…")
        {
            if (origin == null || origin.Length <= maxLength)
            {
                return origin;
            }
            return origin.Substring(0, maxLength).Append(suffix);
        }

        /// <summary>
        /// 字符串截取(中文字符的长度为2)
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="maxLength">截取长度</param>
        /// <param name="suffix">后缀</param>
        /// <returns>截取后的字符串</returns>
        public static string TruncateChinese(string origin, int maxLength, string suffix = "…")
        {
            if (string.IsNullOrEmpty(origin) || maxLength <= 0)
            {
                return string.Empty;
            }

            int originalLength = origin.Length;
            int cutLength = 0;

            while (cutLength < maxLength && cutLength < originalLength)
            {
                //每遇到一个中文，则将目标长度减一。
                if (origin[cutLength] > 128)
                {
                    maxLength--;
                }
                cutLength++;
            }

            if (cutLength < originalLength)
            {
                return origin.Substring(0, cutLength).Append(suffix);
            }
            return origin;
        }

        /// <summary>
        /// 返回指定字符串之前的字符串
        /// </summary>
        /// <param name = "value">源字符串</param>
        /// <param name = "x">指定字符串</param>
        /// <returns></returns>
        public static string GetBefore(this string value, string x)
        {
            var xPos = value.IndexOf(x);
            return xPos == -1 ? String.Empty : value.Substring(0, xPos);
        }

        /// <summary>
        /// 返回指定字符串之间的字符串
        /// </summary>
        /// <param name = "value">源字符串</param>
        /// <param name = "x">左边界</param>
        /// <param name = "y">右边界</param>
        /// <returns></returns>
        public static string GetBetween(this string value, string x, string y)
        {
            var xPos = value.IndexOf(x);
            var yPos = value.LastIndexOf(y);

            if (xPos == -1 || xPos == -1)
                return String.Empty;

            var startIndex = xPos + x.Length;
            return startIndex >= yPos ? String.Empty : value.Substring(startIndex, yPos - startIndex).Trim();
        }

        /// <summary>
        /// 返回指定字符串之后的字符串
        /// </summary>
        /// <param name = "value">源字符串</param>
        /// <param name = "x">指定字符串</param>
        /// <returns></returns>
        public static string GetAfter(this string value, string x)
        {
            var xPos = value.LastIndexOf(x);

            if (xPos == -1)
                return String.Empty;

            var startIndex = xPos + x.Length;
            return startIndex >= value.Length ? String.Empty : value.Substring(startIndex).Trim();
        }

        #endregion

        #region Append

        /// <summary>
        /// 字符串附加
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <param name="toAppend">待附加字符串</param>
        /// <returns>附加后的字符串</returns>
        public static string Append(this string origin, params string[] toAppend)
        {
            if (toAppend.Length < 1)
            {
                return origin ?? string.Empty;
            }

            StringBuilder res = new StringBuilder(origin);

            foreach (var s in toAppend)
            {
                res.Append(s);
            }
            return res.ToString();
        }

        #endregion

        #region  Common

        #region 全角、半角转换

        /// <summary>
        /// 全角转半角
        /// </summary>
        public static string ToDbc(this string sbcCaseString)
        {
            char[] cc = sbcCaseString.ToCharArray();
            for (int i = 0; i < cc.Length; i++)
            {
                if (cc[i] == 12288)
                {
                    // 表示空格    
                    cc[i] = (char) 32;
                    continue;
                }
                if (cc[i] > 65280 && cc[i] < 65375)
                {
                    cc[i] = (char) (cc[i] - 65248);
                }
            }
            return new string(cc);
        }

        /// <summary>
        /// 半角转全角
        /// </summary>
        public static string ToSbc(this string dbcCaseString)
        {
            char[] cc = dbcCaseString.ToCharArray();
            for (int i = 0; i < cc.Length; i++)
            {
                if (cc[i] == 32)
                {
                    // 表示空格    
                    cc[i] = (char) 12288;
                    continue;
                }
                if (cc[i] < 127 && cc[i] > 32)
                {
                    cc[i] = (char) (cc[i] + 65248);
                }
            }
            return new string(cc);
        }

        #endregion

        /// <summary>
        /// 大小写互换
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string SwitchCase(this string input)
        {
            var outputStr = new char[input.Length];
            string res = string.Empty;
            for (int i = 0; i < input.Length; i++)
            {
                if (input[i] >= 'a' && input[i] <= 'z')
                    outputStr[i] = (char) (input[i] - ('a' - 'A'));
                if (input[i] >= 'A' && input[i] <= 'Z')
                    outputStr[i] = (char) (input[i] + ('a' - 'A'));
            }
            return outputStr.Aggregate(res, (current, t) => current + t);
        }

        /// <summary>
        /// 指定字符串在源字符串中出现的次数
        /// </summary>
        /// <param name="input">源字符串</param>
        /// <param name="match">指定字符串或正则表达式</param>
        /// <returns></returns>
        public static int OccurTimes(this string input, string match)
        {
            if (string.IsNullOrEmpty(input))
                return 0;
            Regex tempRegex = new Regex(match);
            return tempRegex.Matches(input).Count;
        }

        /// <summary>
        /// 字符串反转
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Reverse(this string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            return new string(input.Reverse().ToArray());
        }

        /// <summary>
        /// 过滤字符串
        /// </summary>
        /// <param name="input"></param>
        /// <param name="filter">要过滤掉的字符串或正则表达式</param>
        /// <returns></returns>
        public static string FilterOut(this string input, string filter)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            if (string.IsNullOrEmpty(filter))
                return input;
            return input.ReplaceWith(filter, string.Empty);
        }

        /// <summary>
        /// 过滤任何空白字符，包括空格、制表符、换页符等等
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string FilterOutWhitespace(this string input)
        {
            return FilterOut(input, @"\s");
        }

        /// <summary>
        /// 匹配字符串，返回匹配结果
        /// </summary>
        /// <param name="input"></param>
        /// <param name="filter">要匹配的字符串或正则表达式</param>
        /// <returns></returns>
        public static string FilterMatch(this string input, string filter)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;
            if (string.IsNullOrEmpty(filter))
                return string.Empty;
            Regex tempRegex = new Regex(filter);
            MatchCollection collection = tempRegex.Matches(input);
            StringBuilder builder = new StringBuilder();
            foreach (Match match in collection)
            {
                builder.Append(match.Value);
            }
            return builder.ToString();
        }

        /// <summary>
        /// Camel Case
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToCamel(this string s)
        {
            if (s.HasValue() == false)
                return s;
            return s[0].ToString().ToLower() + s.Substring(1);
        }

        /// <summary>
        /// Pascal Case
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToPascal(this string s)
        {
            if (s.HasValue() == false)
                return s;
            return s[0].ToString().ToUpper() + s.Substring(1);
        }

        /// <summary>
        /// 判断字符串是否不为null且不为string.Empty
        /// </summary>
        /// <param name = "value"></param>
        public static bool HasValue(this string value)
        {
            return (string.IsNullOrEmpty(value) == false);
        }

        /// <summary>
        /// 当字符串为null或string.Empty时，返回默认值，否则返回字符串本身
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "defaultValue">默认值</param>
        /// <returns></returns>
        public static string IfHasNoValue(this string value, string defaultValue)
        {
            return (value.HasValue() ? value : defaultValue);
        }

        /// <summary>
        /// 返回格式化后的字符串
        /// </summary>
        /// <param name = "value">格式化字符串</param>
        /// <param name = "parameters">参数</param>
        /// <returns></returns>
        public static string FormatWith(this string value, params object[] parameters)
        {
            return string.Format(value, parameters);
        }

        /// <summary>
        /// 判断字符串中是否包含指定字符串
        /// </summary>
        /// <param name = "inputValue"></param>
        /// <param name = "comparisonValue">指定字符串</param>
        /// <param name = "comparisonType"></param>
        /// <returns></returns>
        public static bool Contains(this string inputValue, string comparisonValue, StringComparison comparisonType)
        {
            return (inputValue.IndexOf(comparisonValue, comparisonType) > -1);
        }

        /// <summary>
        /// 	Loads the string into a LINQ to XML XDocument
        /// </summary>
        /// <param name = "xml">The XML string.</param>
        /// <returns>The XML document object model (XDocument)</returns>
        public static XDocument ToXDocument(this string xml)
        {
            return XDocument.Parse(xml);
        }

        /// <summary>
        /// 	Loads the string into a XML DOM object (XmlDocument)
        /// </summary>
        /// <param name = "xml">The XML string.</param>
        /// <returns>The XML document object model (XmlDocument)</returns>
        public static XmlDocument ToXmlDom(this string xml)
        {
            var document = new XmlDocument();
            document.LoadXml(xml);
            return document;
        }

        /// <summary>
        /// 	Loads the string into a XML XPath DOM (XPathDocument)
        /// </summary>
        /// <param name = "xml">The XML string.</param>
        /// <returns>The XML XPath document object model (XPathNavigator)</returns>
        public static XPathNavigator ToXPath(this string xml)
        {
            var document = new XPathDocument(new StringReader(xml));
            return document.CreateNavigator();
        }

        /// <summary>
        /// 确保字符串以指定前缀开头
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "prefix">前缀</param>
        /// <returns></returns>
        /// <example>
        /// 	<code>
        /// 		var extension = "txt";
        /// 		var fileName = string.Concat(file.Name, extension.EnsureStartsWith("."));
        /// 	</code>
        /// </example>
        public static string EnsureStartsWith(this string value, string prefix)
        {
            return value.StartsWith(prefix) ? value : string.Concat(prefix, value);
        }

        /// <summary>
        /// 确保字符串以指定后缀结尾
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "suffix">后缀</param>
        /// <returns></returns>
        /// <example>
        /// 	<code>
        /// 		var url = "http://www.abc.cn";
        /// 		url = url.EnsureEndsWith("/"));
        /// 	</code>
        /// </example>
        public static string EnsureEndsWith(this string value, string suffix)
        {
            return value.EndsWith(suffix) ? value : string.Concat(value, suffix);
        }

        /// <summary>
        /// 字符串重复N次
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "repeatCount">N</param>
        /// <returns></returns>
        public static string Repeat(this string value, int repeatCount)
        {
            var sb = new StringBuilder();
            repeatCount.Loops(() => sb.Append(value));
            return sb.ToString();
        }

        /// <summary>
        /// 取出字符串中所有数字
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static string ExtractDigits(this string value)
        {
            return string.Join(null, Regex.Split(value, "[^\\d]"));
        }

        /// <summary>
        /// 过滤指定字符
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "removeCharc"></param>
        public static string Remove(this string value, params char[] removeCharc)
        {
            var result = value;
            if (!string.IsNullOrEmpty(result) && removeCharc != null)
                Array.ForEach(removeCharc, c => result = result.Remove(c.ToString()));

            return result;
        }

        /// <summary>
        /// 过滤指定字符串
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "strings"></param>
        public static string Remove(this string value, params string[] strings)
        {
            return strings.Aggregate(value, (current, c) => current.Replace(c, string.Empty));
        }

        /// <summary>
        /// 判断字符串是否为null，或为string.Empty，或只包括空白字符
        /// </summary>
        /// <param name = "value"></param>
        public static bool HasMeaningfulValue(this string value)
        {
            return (!value.HasValue() || value.All(char.IsWhiteSpace));
        }

        /// <summary>
        /// 如果字符串是否为null，或为string.Empty，或只包括空白字符，则返回指定默认值，否则返回字符串本身
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "defaultValue">默认值</param>
        /// <returns></returns>
        public static string IfHasNoMeaningfulValue(this string value, string defaultValue)
        {
            return (value.HasMeaningfulValue() ? defaultValue : value);
        }

        /// <summary>
        /// 英文单数变复数
        /// </summary>
        /// <param name="singular"></param>
        /// <returns></returns>
        public static string ToPlural(this string singular)
        {
            // Multiple words in the form A of B : Apply the plural to the first word only (A)
            int index = singular.LastIndexOf(" of ");
            if (index > 0)
                return (singular.Substring(0, index)) + singular.Remove(0, index).ToPlural();

            // single Word rules
            //sibilant ending rule
            if (singular.EndsWith("sh"))
                return singular + "es";
            if (singular.EndsWith("ch"))
                return singular + "es";
            if (singular.EndsWith("us"))
                return singular + "es";
            if (singular.EndsWith("ss"))
                return singular + "es";
            //-ies rule
            if (singular.EndsWith("y"))
                return singular.Remove(singular.Length - 1, 1) + "ies";
            // -oes rule
            if (singular.EndsWith("o"))
                return singular.Remove(singular.Length - 1, 1) + "oes";
            // -s suffix rule
            return singular + "s";
        }

        /// <summary>
        /// 使当前字符串针对HTML安全进行编码
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="all">是否对所有字符进行编码</param>
        /// <returns></returns>
        public static string ToHtmlSafe(this string s, bool all = false)
        {
            return s.ToHtmlSafe(all, false);
        }

        /// <summary>
        /// 使当前字符串针对HTML安全进行编码
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="all">是否对所有字符进行编码</param>
        /// <param name="replace">是否对空格和换行进行编码</param>
        /// <returns></returns>
        public static string ToHtmlSafe(this string s, bool all, bool replace)
        {
            if (s.HasMeaningfulValue())
                return string.Empty;
            var entities = new[]
                           {
                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
                               25, 26, 28, 29, 30, 31, 34, 39, 38, 60, 62, 123, 124, 125, 126, 127, 160, 161, 162, 163,
                               164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
                               182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 215, 247, 192, 193, 194, 195, 196, 197,
                               198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
                               216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
                               234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
                               252, 253, 254, 255, 256, 8704, 8706, 8707, 8709, 8711, 8712, 8713, 8715, 8719, 8721, 8722
                               , 8727, 8730, 8733, 8734, 8736, 8743, 8744, 8745, 8746, 8747, 8756, 8764, 8773, 8776,
                               8800, 8801, 8804, 8805, 8834, 8835, 8836, 8838, 8839, 8853, 8855, 8869, 8901, 913, 914,
                               915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933,
                               934, 935, 936, 937, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958,
                               959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 977, 978, 982, 338, 339, 352, 353,
                               376, 402, 710, 732, 8194, 8195, 8201, 8204, 8205, 8206, 8207, 8211, 8212, 8216, 8217,
                               8218, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8254, 8364,
                               8482, 8592, 8593, 8594, 8595, 8596, 8629, 8968, 8969, 8970, 8971, 9674, 9824, 9827, 9829,
                               9830
                           };
            var sb = new StringBuilder();
            foreach (var c in s)
            {
                if (all || entities.Contains(c))
                    sb.Append("&#" + ((int) c) + ";");
                else
                    sb.Append(c);
            }

            return replace
                       ? sb.Replace("\r\n", "<br />").Replace("\n", "<br />").Replace(" ", "&nbsp;").ToString()
                       : sb.ToString();
        }

        #endregion

        #region Regex based

        /// <summary>
        /// 判断字符串是否匹配指定正则表达式
        /// </summary>
        /// <param name = "value">字符串</param>
        /// <param name = "regexPattern">正则表达式</param>
        /// <returns></returns>
        public static bool IsMatch(this string value, string regexPattern)
        {
            return IsMatch(value, regexPattern, RegexOptions.None);
        }

        /// <summary>
        /// 判断字符串是否匹配指定正则表达式
        /// </summary>
        /// <param name = "value">字符串</param>
        /// <param name = "regexPattern">正则表达式</param>
        /// <param name = "options">正则操作属性</param>
        /// <returns></returns>
        public static bool IsMatch(this string value, string regexPattern, RegexOptions options)
        {
            return Regex.IsMatch(value, regexPattern, options);
        }

        /// <summary>
        /// 通过正则表达式进行字符串替换
        /// </summary>
        /// <param name = "value">字符串</param>
        /// <param name = "regexPattern">正则表达式</param>
        /// <param name = "replaceValue">替换值</param>
        /// <returns></returns>
        /// <example>
        /// 	<code>
        /// 		var s = "12345";
        /// 		var replaced = s.ReplaceWith(@"\d", m => string.Concat(" -", m.Value, "- "));
        /// 	</code>
        /// </example>
        public static string ReplaceWith(this string value, string regexPattern, string replaceValue)
        {
            return ReplaceWith(value, regexPattern, replaceValue, RegexOptions.None);
        }

        /// <summary>
        /// 通过正则表达式进行字符串替换
        /// </summary>
        /// <param name = "value">字符串</param>
        /// <param name = "regexPattern">正则表达式</param>
        /// <param name = "replaceValue">替换值</param>
        /// <param name = "options">正则操作属性</param>
        /// <returns></returns>
        public static string ReplaceWith(this string value,
                                         string regexPattern,
                                         string replaceValue,
                                         RegexOptions options)
        {
            return Regex.Replace(value, regexPattern, replaceValue, options);
        }

        /// <summary>
        /// 	Uses regular expressions to replace parts of a string.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <param name = "evaluator">The replacement method / lambda expression.</param>
        /// <returns></returns>
        public static string ReplaceWith(this string value, string regexPattern, MatchEvaluator evaluator)
        {
            return ReplaceWith(value, regexPattern, RegexOptions.None, evaluator);
        }

        /// <summary>
        /// 	Uses regular expressions to replace parts of a string.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <param name = "options">The regular expression options.</param>
        /// <param name = "evaluator">The replacement method / lambda expression.</param>
        /// <returns>The newly created string</returns>
        public static string ReplaceWith(this string value,
                                         string regexPattern,
                                         RegexOptions options,
                                         MatchEvaluator evaluator)
        {
            return Regex.Replace(value, regexPattern, evaluator, options);
        }

        /// <summary>
        /// 	Uses regular expressions to determine all matches of a given regex pattern.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <returns>A collection of all matches</returns>
        public static MatchCollection GetMatches(this string value, string regexPattern)
        {
            return GetMatches(value, regexPattern, RegexOptions.None);
        }

        /// <summary>
        /// 	Uses regular expressions to determine all matches of a given regex pattern.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <param name = "options">The regular expression options.</param>
        /// <returns>A collection of all matches</returns>
        public static MatchCollection GetMatches(this string value, string regexPattern, RegexOptions options)
        {
            return Regex.Matches(value, regexPattern, options);
        }

        /// <summary>
        /// 	Uses regular expressions to determine all matches of a given regex pattern and returns them as string enumeration.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <returns>An enumeration of matching strings</returns>
        /// <example>
        /// 	<code>
        /// 		var s = "12345";
        /// 		foreach(var number in s.GetMatchingValues(@"\d")) {
        /// 		Console.WriteLine(number);
        /// 		}
        /// 	</code>
        /// </example>
        public static IEnumerable<string> GetMatchValues(this string value, string regexPattern)
        {
            return GetMatchValues(value, regexPattern, RegexOptions.None);
        }

        /// <summary>
        /// 	Uses regular expressions to determine all matches of a given regex pattern and returns them as string enumeration.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <param name = "options">The regular expression options.</param>
        /// <returns>An enumeration of matching strings</returns>
        /// <example>
        /// 	<code>
        /// 		var s = "12345";
        /// 		foreach(var number in s.GetMatchingValues(@"\d")) {
        /// 		Console.WriteLine(number);
        /// 		}
        /// 	</code>
        /// </example>
        public static IEnumerable<string> GetMatchValues(this string value, string regexPattern, RegexOptions options)
        {
            return from Match match in GetMatches(value, regexPattern, options)
                   where match.Success
                   select match.Value;
        }

        /// <summary>
        /// 	Uses regular expressions to split a string into parts.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <returns>The splitted string array</returns>
        public static string[] Split(this string value, string regexPattern)
        {
            return value.Split(regexPattern, RegexOptions.None);
        }

        /// <summary>
        /// 	Uses regular expressions to split a string into parts.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "regexPattern">The regular expression pattern.</param>
        /// <param name = "options">The regular expression options.</param>
        /// <returns>The splitted string array</returns>
        public static string[] Split(this string value, string regexPattern, RegexOptions options)
        {
            return Regex.Split(value, regexPattern, options);
        }

        /// <summary>
        /// 	Splits the given string into words and returns a string array.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <returns>The splitted string array</returns>
        public static string[] GetWords(this string value)
        {
            return value.Split(@"\W");
        }

        /// <summary>
        /// 返回字符串中第N个单词
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "index"></param>
        /// <returns>如果N超出索引范围，返回空字符串</returns>
        public static string GetWordByIndex(this string value, int index)
        {
            var words = value.GetWords();

            if ((index < 0) || (index > words.Length - 1))
                return string.Empty;

            return words[index];
        }

        /// <summary>
        /// Add space on every upper character
        /// </summary>
        /// <param name="value">The input string.</param>
        /// <returns>The adjusted string.</returns>
        public static string SpaceOnUpper(this string value)
        {
            return Regex.Replace(value, "([A-Z])(?=[a-z])|(?<=[a-z])([A-Z]|[0-9]+)", " $1$2").TrimStart();
        }

        #endregion

        #region Bytes & Base64

        /// <summary>
        /// 	Converts the string to a byte-array using the supplied encoding
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "encoding">The encoding to be used.</param>
        /// <returns>The created byte array</returns>
        /// <example>
        /// 	<code>
        /// 		var value = "Hello World";
        /// 		var ansiBytes = value.ToBytes(Encoding.GetEncoding(1252)); // 1252 = ANSI
        /// 		var utf8Bytes = value.ToBytes(Encoding.UTF8);
        /// 	</code>
        /// </example>
        public static byte[] ToBytes(this string value, Encoding encoding = null)
        {
            return (encoding ?? Encoding.UTF8).GetBytes(value);
        }

        /// <summary>
        /// 	Encodes the input value to a Base64 string using the supplied encoding.
        /// </summary>
        /// <param name = "value">The input value.</param>
        /// <param name = "encoding">The encoding.</param>
        /// <returns>The Base 64 encoded string</returns>
        public static string EncodeBase64(this string value, Encoding encoding = null)
        {
            return Convert.ToBase64String(value.ToBytes(encoding));
        }

        /// <summary>
        /// 	Decodes a Base 64 encoded value to a string using the supplied encoding.
        /// </summary>
        /// <param name = "encodedValue">The Base 64 encoded value.</param>
        /// <param name = "encoding">The encoding.</param>
        /// <returns>The decoded string</returns>
        public static string DecodeBase64(this string encodedValue, Encoding encoding = null)
        {
            var bytes = Decode(encodedValue);
            return (encoding ?? Encoding.UTF8).GetString(bytes);
        }

        private static byte[] Decode(string value)
        {
            try
            {
                return Convert.FromBase64String(value);
            }
            catch (FormatException)
            {
                return new byte[0];
            }
        }

        #region Compress

        /// <summary>
        /// Compresses the specified instance.
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <param name="encoding">The encoding </param>
        /// <returns></returns>
        public static string Compress(this string instance, Encoding encoding = null)
        {
            Guard.NotDefault(instance, "instance");

            byte[] binary = (encoding ?? Encoding.UTF8).GetBytes(instance);
            byte[] compressed;

            using (MemoryStream ms = new MemoryStream())
            {
                using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress))
                {
                    zip.Write(binary, 0, binary.Length);
                }

                compressed = ms.ToArray();
            }

            byte[] compressedWithLength = new byte[compressed.Length + 4];

            Buffer.BlockCopy(compressed, 0, compressedWithLength, 4, compressed.Length);
            Buffer.BlockCopy(BitConverter.GetBytes(binary.Length), 0, compressedWithLength, 0, 4);

            return Convert.ToBase64String(compressedWithLength);
        }

        /// <summary>
        /// Decompresses the specified instance.
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <param name="encoding">The encoding.</param>
        /// <returns></returns>
        public static string Decompress(this string instance, Encoding encoding = null)
        {
            Guard.NotDefault(instance, "instance");

            var compressed = Decode(instance);

            if (compressed.Length < 4)
            {
                return string.Empty;
            }

            using (var stream = new MemoryStream())
            {
                var length = BitConverter.ToInt32(compressed, 0);
                stream.Write(compressed, 4, compressed.Length - 4);

                var binary = new byte[length];

                stream.Seek(0, SeekOrigin.Begin);

                using (var zip = new GZipStream(stream, CompressionMode.Decompress))
                {
                    try
                    {
                        zip.Read(binary, 0, binary.Length);

                        return (encoding ?? Encoding.UTF8).GetString(binary);
                    }
                    catch (InvalidDataException)
                    {
                        return string.Empty;
                    }
                }
            }
        }

        #endregion

        #endregion
    }
}